from PyQt5.QtWidgets import QWidget, QFrame

from config import make_logging
from kxml import KXml
from winmode import KWindow, EditWinMode
from kwidget import *

LOG = make_logging("gui")

class WidgetFactory:
    def __new__(self):
        if not hasattr(self, "instance"):
            self.instance = super().__new__(self)
        return self.instance

    def __init__(self, dict_widget=None):
        # 当没有传入dict_widget时，使用原有的dict
        if dict_widget is not None:
            self._dict_widget = dict_widget
        elif not hasattr(self, "_dict_widget"):
            self._dict_widget = None

    def new(self, parent, dict_widget=None):
        # 当传入特定的dict_widget时，使用指定参数值
        if dict_widget is None:
            dict_widget = self._dict_widget
        if "type" not in dict_widget:
            raise Exception("Not found the type of Gui widget.")
        widget_class_name = dict_widget["type"]
        return eval(widget_class_name)(dict_widget, parent)


class KPage:
    def __init__(self, dict_elem, parent):
        self.ui = QFrame(parent)
        self.dict_elem = dict_elem
        self.list_widgets = []

    def parse_elems(self):
        if "widgets" not in self.dict_elem:
            LOG.info("Not found any 【widget】 in xml file")
            # continue
        else:
            self.install_widgets(self.dict_elem["widgets"])

    def create_widget(self, dict_widget):
        factory = WidgetFactory()  # 单例
        widget = factory.new(parent=self.ui, dict_widget=dict_widget)
        widget.run()
        self.list_widgets.append(widget)

    def install_widgets(self, list_widgets):
        for dict_widget in list_widgets:
            LOG.debug("widget --> %s" % dict_widget)
            self.create_widget(dict_widget)

    def uninstall_widgets(self):
        for widget in self.list_widgets:
            widget.close()
        self.list_widgets.clear()

    def run(self):
        self.parse_elems()
        self.ui.show()


class KLayout:
    pass


class KFrame(KWindow):
    """ 用于GUI图形窗口的显示 """
    def __init__(self, xml_filepath):
        super().__init__()
        self.editmode = EditWinMode()
        self.xml = KXml(xml_filepath)
        self.dict_elem = self.xml.load_file()

        self.dict_pages = {}  # dict of KPage
        self.active_page = None

    def run(self):
        self.install_pages()
        self.install_frame()
        self.install_plugins()
        self.active_page.run()
        self.show()

        self.editmode.run()

    def keyPressEvent(self, event):
        editwin = self.editmode.get_window_obj()
        if event.modifiers() == Qt.AltModifier and event.key() == Qt.Key_R:
            # 运行模式
            LOG.debug("Switch to Running Mode")
            if editwin.isVisible():
                editwin.close()
            else:
                QMessageBox.information(self, "Mode Switch Error", "您已处于运行模式")
        elif event.modifiers() == Qt.AltModifier and event.key() == Qt.Key_E:
            # 编辑模式
            LOG.debug("Switch to Edit Mode")
            self.show_editwin()
        elif event.modifiers() == Qt.AltModifier and event.key() == Qt.Key_S:
            reply = QMessageBox.question(self, "保存XML", "是否确认将当前页面保存为xml格式？",
                    QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
            if reply == QMessageBox.Yes:
                LOG.debug("Save to Xml File")
                self.save_xml()
        # elif event.modifiers() == Qt.AltModifier and event.key() == Qt.Key_E:
        #     pass
        # elif event.modifiers() == Qt.AltModifier and event.key() == Qt.Key_E:
        #     pass


    def install_pages(self):
        if "pages" not in self.dict_elem:
            LOG.error("Not found any 【page】 in xml file")
            Exception("No_Element_pages")
        list_pages = self.dict_elem["pages"]

        for dict_page in list_pages:
            if "name" not in dict_page:
                Exception("A page has no the tag 【name】 so can't market it")
            page_name = dict_page["name"]
            self.dict_pages[page_name] = KPage(dict_page, self)

    def install_plugins(self):
        if "plugins" not in self.dict_elem:
            LOG.info("Not found any 【plugin】 in xml file")
            return
        list_plugins = self.dict_elem["plugins"]
        pass

    def install_frame(self):
        self.install_pages()  # 初始化 self.dict_pages

        if "window" not in self.dict_elem:
            LOG.error("Not found the window frame 【window】 in xml file")
            Exception("No_Element_window")
        dict_kiv = self.dict_elem["window"]

        if "name" in dict_kiv:
            self.setWindowTitle(dict_kiv["name"])
        if "size" in dict_kiv:
            str_x, str_y = dict_kiv["size"].split(",")
            self.resize(int(str_x), int(str_y))
        if "default_page" in dict_kiv:
            dft_page = dict_kiv["default_page"]
            self.active_page = self.dict_pages[dft_page]
        else:
            Exception("Not found 【default_page】 in xml file")

    def save_xml(self):
        """ 将改动后的 self.dict_elem 保存为 xml """
        self.xml.dump_file(self.dict_elem)

    def show_editwin(self):
        winobj = self.editmode.get_window_obj()
        if winobj.isVisible():
            QMessageBox.information(self, "Mode Switch Error", "您已处于编辑模式")
        else:
            self.editmode.update(self.active_page)
            winobj.show()

    def switch_page(self, page_name):
        self.active_page.run()
        pass


# class KComponent(ABC):
#     """ 基本结构，包含ui图元和dict图元信息 """
#     def __init__(self, dict_elem):
#         self.ui = QWidget()
#         self.dict_elem = dict_elem

#     def get_qt_obj(self):
#         return self.ui
